/*
** Haaf's Game Engine 1.7
** Copyright (C) 2003-2007, Relish Games
** hge.relishgames.com
**
** hgeGUI helper class implementation
*/


#include "..\..\include\hgegui.h"


HGE *hgeGUI::hge=0;
HGE *hgeGUIObject::hge=0;


hgeGUI::hgeGUI()
{
    hge=hgeCreate(HGE_VERSION);

    ctrls=0;
    ctrlLock=0;
    ctrlFocus=0;
    ctrlOver=0;
    navmode=HGEGUI_NONAVKEYS;
    bLPressed=bLReleased=false;
    bRPressed=bRReleased=false;
    nWheel=0;
    mx=my=0.0f;
    nEnterLeave=0;
    sprCursor=0;
}

hgeGUI::~hgeGUI()
{
    hgeGUIObject *ctrl=ctrls, *nextctrl;

    while(ctrl) {
        nextctrl=ctrl->next;
        delete ctrl;
        ctrl=nextctrl;
    }

    hge->Release();
}

void hgeGUI::AddCtrl(hgeGUIObject *ctrl)
{
    hgeGUIObject *last=ctrls;

    ctrl->gui=this;

    if(!ctrls) {
        ctrls=ctrl;
        ctrl->prev=0;
        ctrl->next=0;
    } else {
        while(last->next) {
            last=last->next;
        }
        last->next=ctrl;
        ctrl->prev=last;
        ctrl->next=0;
    }
}

void hgeGUI::DelCtrl(int id)
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        if(ctrl->id == id) {
            if(ctrl->prev) {
                ctrl->prev->next = ctrl->next;
            } else {
                ctrls = ctrl->next;
            }
            if(ctrl->next) {
                ctrl->next->prev = ctrl->prev;
            }
            delete ctrl;
            return;
        }
        ctrl=ctrl->next;
    }
}

hgeGUIObject* hgeGUI::GetCtrl(int id) const
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        if(ctrl->id == id) {
            return ctrl;
        }
        ctrl=ctrl->next;
    }

    return NULL;
}

void hgeGUI::MoveCtrl(int id, float x, float y)
{
    hgeGUIObject *ctrl=GetCtrl(id);
    ctrl->rect.x2=x + (ctrl->rect.x2 - ctrl->rect.x1);
    ctrl->rect.y2=y + (ctrl->rect.y2 - ctrl->rect.y1);
    ctrl->rect.x1=x;
    ctrl->rect.y1=y;
}

void hgeGUI::ShowCtrl(int id, bool bVisible)
{
    GetCtrl(id)->bVisible=bVisible;
}

void hgeGUI::EnableCtrl(int id, bool bEnabled)
{
    GetCtrl(id)->bEnabled=bEnabled;
}

void hgeGUI::SetNavMode(int mode)
{
    navmode=mode;
}

void hgeGUI::SetCursor(hgeSprite *spr)
{
    sprCursor=spr;
}


void hgeGUI::SetColor(hgeU32 color)
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        ctrl->SetColor(color);
        ctrl=ctrl->next;
    }
}


void hgeGUI::Reset()
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        ctrl->Reset();
        ctrl=ctrl->next;
    }

    ctrlLock=0;
    ctrlOver=0;
    ctrlFocus=0;
}


void hgeGUI::Move(float dx, float dy)
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        ctrl->rect.x1 += dx;
        ctrl->rect.y1 += dy;
        ctrl->rect.x2 += dx;
        ctrl->rect.y2 += dy;

        ctrl=ctrl->next;
    }
}


void hgeGUI::SetFocus(int id)
{
    hgeGUIObject *ctrlNewFocus=GetCtrl(id);

    if(ctrlNewFocus==ctrlFocus) {
        return;
    }
    if(!ctrlNewFocus) {
        if(ctrlFocus) {
            ctrlFocus->Focus(false);
        }
        ctrlFocus=0;
    } else if(!ctrlNewFocus->bStatic && ctrlNewFocus->bVisible && ctrlNewFocus->bEnabled) {
        if(ctrlFocus) {
            ctrlFocus->Focus(false);
        }
        if(ctrlNewFocus) {
            ctrlNewFocus->Focus(true);
        }
        ctrlFocus=ctrlNewFocus;
    }
}

int hgeGUI::GetFocus() const
{
    if(ctrlFocus) {
        return ctrlFocus->id;
    } else {
        return 0;
    }
}

void hgeGUI::Enter()
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        ctrl->Enter();
        ctrl=ctrl->next;
    }

    nEnterLeave=2;
}

void hgeGUI::Leave()
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        ctrl->Leave();
        ctrl=ctrl->next;
    }

    ctrlFocus=0;
    ctrlOver=0;
    ctrlLock=0;
    nEnterLeave=1;
}

void hgeGUI::Render()
{
    hgeGUIObject *ctrl=ctrls;

    while(ctrl) {
        if(ctrl->bVisible) {
            ctrl->Render();
        }
        ctrl=ctrl->next;
    }

    if(hge->Input_IsMouseOver() && sprCursor) {
        sprCursor->Render(mx,my);
    }
}

int hgeGUI::Update(float dt)
{
    bool bDone;
    int key;
    hgeGUIObject *ctrl;

// Update the mouse variables

    hge->Input_GetMousePos(&mx, &my);
    bLPressed  = hge->Input_KeyDown(HGEK_LBUTTON);
    bLReleased = hge->Input_KeyUp(HGEK_LBUTTON);
    bRPressed  = hge->Input_KeyDown(HGEK_RBUTTON);
    bRReleased = hge->Input_KeyUp(HGEK_RBUTTON);
    nWheel=hge->Input_GetMouseWheel();

// Update all controls

    ctrl=ctrls;
    while(ctrl) {
        ctrl->Update(dt);
        ctrl=ctrl->next;
    }

// Handle Enter/Leave

    if(nEnterLeave) {
        ctrl=ctrls;
        bDone=true;
        while(ctrl) {
            if(!ctrl->IsDone()) {
                bDone=false;
                break;
            }
            ctrl=ctrl->next;
        }
        if(!bDone) {
            return 0;
        } else {
            if(nEnterLeave==1) {
                return -1;
            } else {
                nEnterLeave=0;
            }
        }
    }

// Handle keys

    key=hge->Input_GetKey();
    if(((navmode & HGEGUI_LEFTRIGHT) && key==HGEK_LEFT) ||
            ((navmode & HGEGUI_UPDOWN) && key==HGEK_UP)) {
        ctrl=ctrlFocus;
        if(!ctrl) {
            ctrl=ctrls;
            if(!ctrl) {
                return 0;
            }
        }
        do {
            ctrl=ctrl->prev;
            if(!ctrl && ((navmode & HGEGUI_CYCLED) || !ctrlFocus)) {
                ctrl=ctrls;
                while(ctrl->next) {
                    ctrl=ctrl->next;
                }
            }
            if(!ctrl || ctrl==ctrlFocus) {
                break;
            }
        } while(ctrl->bStatic==true || ctrl->bVisible==false || ctrl->bEnabled==false);

        if(ctrl && ctrl!=ctrlFocus) {
            if(ctrlFocus) {
                ctrlFocus->Focus(false);
            }
            if(ctrl) {
                ctrl->Focus(true);
            }
            ctrlFocus=ctrl;
        }
    } else if(((navmode & HGEGUI_LEFTRIGHT) && key==HGEK_RIGHT) ||
              ((navmode & HGEGUI_UPDOWN) && key==HGEK_DOWN)) {
        ctrl=ctrlFocus;
        if(!ctrl) {
            ctrl=ctrls;
            if(!ctrl) {
                return 0;
            }
            while(ctrl->next) {
                ctrl=ctrl->next;
            }
        }
        do {
            ctrl=ctrl->next;
            if(!ctrl && ((navmode & HGEGUI_CYCLED) || !ctrlFocus)) {
                ctrl=ctrls;
            }
            if(!ctrl || ctrl==ctrlFocus) {
                break;
            }
        } while(ctrl->bStatic==true || ctrl->bVisible==false || ctrl->bEnabled==false);

        if(ctrl && ctrl!=ctrlFocus) {
            if(ctrlFocus) {
                ctrlFocus->Focus(false);
            }
            if(ctrl) {
                ctrl->Focus(true);
            }
            ctrlFocus=ctrl;
        }
    } else if(ctrlFocus && key && key!=HGEK_LBUTTON && key!=HGEK_RBUTTON) {
        if(ctrlFocus->KeyClick(key, hge->Input_GetChar())) {
            return ctrlFocus->id;
        }
    }

// Handle mouse

    bool bLDown = hge->Input_GetKeyState(HGEK_LBUTTON);
    bool bRDown = hge->Input_GetKeyState(HGEK_RBUTTON);

    if(ctrlLock) {
        ctrl=ctrlLock;
        if(!bLDown && !bRDown) {
            ctrlLock=0;
        }
        if(ProcessCtrl(ctrl)) {
            return ctrl->id;
        }
    } else {
        // Find last (topmost) control

        ctrl=ctrls;
        if(ctrl)
            while(ctrl->next) {
                ctrl=ctrl->next;
            }

        while(ctrl) {
            if(ctrl->rect.TestPoint(mx,my) && ctrl->bEnabled) {
                if(ctrlOver != ctrl) {
                    if(ctrlOver) {
                        ctrlOver->MouseOver(false);
                    }
                    ctrl->MouseOver(true);
                    ctrlOver=ctrl;
                }

                if(ProcessCtrl(ctrl)) {
                    return ctrl->id;
                } else {
                    return 0;
                }
            }
            ctrl=ctrl->prev;
        }

        if(ctrlOver) {
            ctrlOver->MouseOver(false);
            ctrlOver=0;
        }

    }

    return 0;
}

bool hgeGUI::ProcessCtrl(hgeGUIObject *ctrl)
{
    bool bResult=false;

    if(bLPressed)	{
        ctrlLock=ctrl;
        SetFocus(ctrl->id);
        bResult=bResult || ctrl->MouseLButton(true);
    }
    if(bRPressed)	{
        ctrlLock=ctrl;
        SetFocus(ctrl->id);
        bResult=bResult || ctrl->MouseRButton(true);
    }
    if(bLReleased)	{
        bResult=bResult || ctrl->MouseLButton(false);
    }
    if(bRReleased)	{
        bResult=bResult || ctrl->MouseRButton(false);
    }
    if(nWheel)		{
        bResult=bResult || ctrl->MouseWheel(nWheel);
    }
    bResult=bResult || ctrl->MouseMove(mx-ctrl->rect.x1,my-ctrl->rect.y1);

    return bResult;
}



